package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net"
	"reflect"
	"socket_golang/service"
	"strconv"
	"strings"

	_ "github.com/go-sql-driver/mysql"
)

//Socket侦听参数
const tcp_url = "0.0.0.0:21231"

func main() {

	//初始化数据库连接
	db := service.InitDB()

	//TCP listen
	listener, err := net.Listen("tcp", tcp_url)
	if err != nil {
		log.Fatal("listen error:", err)
	}
	log.Println("TCP server start..., listen: ", tcp_url)
	//tcp accept loop
	for {
		socket, err := listener.Accept()
		if err != nil {
			log.Println("tcp accept error:", err)
			continue
		}

		go process(socket, db)
	}
}

//socket处理, 拆解输入json、封装输出json，依据json中的method调用业务函数
func process(socket net.Conn, db service.DB) {

	//关闭socket
	defer socket.Close()
	//捕获goroutine可能抛出的panic
	defer func() {
		if err := recover(); err != nil {
			log.Println("goroutine error: ", err)
		}
	}()

	//读取req json长度
	buf := make([]byte, 12) //长度行总是12字节
	readN, readErr := socket.Read(buf)
	if readErr != nil {
		log.Println("socket read json error", readErr)
	}
	bufStr := string(buf[:readN])
	lenStr := strings.Trim(bufStr, "\r\n") //去除行尾的回车换行
	lenStr = strings.Trim(lenStr, " ")     //去除行左的空格
	jsonLen, _ := strconv.Atoi(lenStr)     //获取json的字节长度

	//读取req json
	jsonBuf := make([]byte, jsonLen)
	_, readErr = socket.Read(jsonBuf)
	if readErr != nil {
		log.Println("socket read json error", readErr)
		return
	}
	// log.Println("|", bufStr, string(jsonBuf[:n]), "|")

	//解析req json
	var jsonMap map[string]interface{}
	if err := json.Unmarshal([]byte(jsonBuf), &jsonMap); err != nil {
		log.Println("Request json error: ", err)
		return
	}
	methodName := jsonMap["head"].(map[string]interface{})["method"].(string) //方法名称
	reqMap := jsonMap["data"].(map[string]interface{})                        //方法参数
	log.Println("method: ", methodName)
	log.Println("reqMap: ", reqMap)

	//反射方法名称
	method := reflect.ValueOf(db).MethodByName(methodName)
	if !method.IsValid() {
		log.Println("Method not found!")
		return
	}
	//反射方法参数
	args := []reflect.Value{reflect.ValueOf(reqMap)}
	//反射方法调用
	reflectRsp := method.Call(args)
	//反射方法返回值
	rsp := reflectRsp[0].Interface()
	//返回值转json
	rspBytes, err := json.Marshal(rsp)
	if err != nil {
		log.Println("json.Marshal error: ", err)
		return
	}

	//socket返回
	lenRsp := fmt.Sprintf("%10d\r\n", len(rspBytes)) //长度行（12字节，左补空格，\r\n结尾）
	socket.Write([]byte(lenRsp))                     //socket返回 长度行
	socket.Write(rspBytes)                           //socket返回 rsp json
}
